﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Shapes;


namespace LayoutPlanning.Helpers
{
    public class Collision
    {
        public static void ProjectPolygon(Vector axis, IList<Point> polygon,
            ref double min, ref double max)
        {
            double dotProduct = Vector.Multiply(axis, new Vector(polygon[0].X, polygon[0].Y));
            min = dotProduct;
            max = dotProduct;
            for (int i = 0; i < polygon.Count; i++)
            {
                var vector = new Vector(polygon[i].X, polygon[i].Y);
                dotProduct = Vector.Multiply(vector, axis);
                if (dotProduct < min)
                    min = dotProduct;

                else if (dotProduct > max)
                    max = dotProduct;
            }
        }

        public static double IntervalDistance(double minA, double maxA, double minB, double maxB)
        {
            if (minA < minB)
                return minB - maxA;
            return minA - maxB;
        }

        public static bool PolygonCollision(IList<Point> polygonA, IList<Point> polygonB)
        {
            bool res = true;
            int edgeCountA = polygonA.Count - 1;
            int edgeCountB = polygonB.Count - 1;
            Vector edge;

            // Loop through all the edges of both polygons
            for (int edgeIndex = 0; edgeIndex < edgeCountA + edgeCountB; edgeIndex++)
            {
                if (edgeIndex == edgeCountA - 1)
                    edge = new Vector(polygonA[0].X - polygonA[edgeIndex].X,
                        polygonA[0].Y - polygonA[edgeIndex].Y);

                else if (edgeIndex < edgeCountA)
                    edge = new Vector(polygonA[edgeIndex + 1].X - polygonA[edgeIndex].X,
                        polygonA[edgeIndex + 1].Y - polygonA[edgeIndex].Y);
                else if (edgeIndex == edgeCountB - 1)
                    edge = new Vector(polygonB[0].X - polygonB[edgeIndex - edgeCountA].X,
                        polygonB[0].Y - polygonB[edgeIndex - edgeCountA].Y);
                else
                    edge =
                        new Vector(
                            polygonB[edgeIndex - edgeCountA + 1].X - polygonB[edgeIndex - edgeCountA].X,
                            polygonB[edgeIndex - edgeCountA + 1].Y - polygonB[edgeIndex - edgeCountA].Y);


                // ===== 1. Find if the polygons are currently intersecting =====
                // Find the axis perpendicular to the current edge
                Vector axis = new Vector(-edge.Y, edge.X);
                axis.Normalize();

                // Find the projection of the polygon on the current axis
                double minA = 0;
                double minB = 0;
                double maxA = 0;
                double maxB = 0;
                ProjectPolygon(axis, polygonA, ref minA, ref maxA);
                ProjectPolygon(axis, polygonB, ref minB, ref maxB);

                // Check if the polygon projections are currentlty intersecting
                if (IntervalDistance(minA, maxA, minB, maxB) > 0)
                    return false;
            }
            return res;
        }
    }
}